﻿using System;
using System.Collections.Generic;
using System.Windows.Input;
using DataModel;
using DynamicLoader;
using SSCCMembership.Services.Abilities;
using SSCCMembership.Services.Login;
using com = DataModel.Commands;

namespace SSCCMembership.ViewModels
{
    public class LoginViewModel : ViewModelBase
    {
        const string NonTechnicalErrorMessage = "There was an unknown error while logging in.";

        string username;
        string password;
        bool inProgress = false;
        string status;

        LoginServiceClient LoginService = new LoginServiceClient();
        AbilitiesServiceClient AbilitiesService = new AbilitiesServiceClient();

        /// <summary>
        /// The user's username.
        /// </summary>
        public string Username
        {
            get { return username; }
            set
            {
                if (username != value)
                {
                    SetErrorMessageIf(value == "", new ErrorMessage("Username", "You must enter a username."));
                    username = value;
                    OnPropertyChanged("Username");
                }
            }
        }
        /// <summary>
        /// The user's password.
        /// </summary>
        public string Password
        {
            get { return password; }
            set
            {
                if (password != value)
                {
                    SetErrorMessageIf(value == "", new ErrorMessage("Password", "You must enter a password."));
                    password = value;
                    OnPropertyChanged("Password");
                }
            }
        }

        bool InProgress
        {
            get { return inProgress; }
            set
            {
                if (inProgress != value)
                {
                    inProgress = value;
                    if (InProgress)
                        BusyIndicator.Show("Attempting to Log In");
                    else
                        BusyIndicator.Hide();
                    //OnPropertyChanged("InProgress", "NotInProgress");
                }
            }
        }
        bool NotInProgress { get { return !InProgress; } set { InProgress = !value; } }

        /// <summary>
        /// The curent status
        /// </summary>
        public string Status
        {
            get { return status; }
            private set
            {
                if (status != value)
                {
                    status = value;
                    OnPropertyChanged("Status");
                }
            }
        }

        /// <summary>
        /// Occurs whenever the user's cursor should 
        /// probably move back to the username box.
        /// </summary>
        public event EventHandler FocusUsername;
        /// <summary>
        /// Occurs after a successful login.
        /// </summary>
        public event EventHandler LoggedIn;

        /// <summary>
        /// Initiates the signin proccess.
        /// </summary>
        public ICommand SignIn { get { return new com.ConditionCommand(DoSignIn, new com.HasNetworkConnection()); } }
        
        //Initiate the sign in progress && check validation rules.
        void DoSignIn()
        {
            SetErrorMessageIf(String.IsNullOrEmpty(Username), new ErrorMessage("Username", "You must enter a username."));
            SetErrorMessageIf(String.IsNullOrEmpty(Password), new ErrorMessage("Password", "You must enter a password."));
            if (HasErrors)
            {
                BusyIndicator.Show("You must enter a username and password.", HasProgress: false, SecondsTimeout: 5, EnableUserClose: true);
            }
            else
            {
                InProgress = true;
                try
                {
                    Cache.Stop();
                    LoginService.LoginCompleted += OnLoginCompleted;
                    LoginService.LoginAsync(Username, Password, null, false);
                }
                catch (Exception)
                {
                    InProgress = false;
                }
            }
        }
        //When the login has completed, either successfully or not.
        void OnLoginCompleted(object sender, LoginCompletedEventArgs e)
        {
            InProgress = false;
            if (e.Error != null)
            {
                //There was a technical error.
                HandleError(e.Error.GetBaseException().Message);
            }
            else if (!e.Result.Success)
            {
                //There was a technical error which could not be logged to the database.
                HandleError(e.Result.FailureMessage);
            }
            else
            {
                if (e.Result.Value)
                {
                    //Success
                    Status = "Success";
                    BusyIndicator.Show("Success, Checking Security Permissions");
                    //Load Abilities
                    AbilitiesService.GetAbilitiesCompleted += OnAbilitiesLoaded;
                    AbilitiesService.GetAbilitiesAsync();
                }
                else
                {
                    Cache.Start();
                    //Failure
                    Status = "Your Username or Password was incorrect";
                    BusyIndicator.Show(() =>
                    {
                        Username = "";
                        Password = "";
                        OnFocusUsername();
                    }, "Your Username or Password was incorrect", HasProgress: false, SecondsTimeout: 2, EnableUserClose: true);
                }
            }
        }
        //When the abilities have been loaded
        void OnAbilitiesLoaded(object sender, GetAbilitiesCompletedEventArgs e)
        {
            BusyIndicator.Hide();
            if (!e.Cancelled & e.Error == null)
            {
                SecurityLib.Security.UserRoles = e.Result;
                OnLoggedIn();
            }
            else
            {
                SecurityLib.Security.UserRoles = new List<string>();
                BusyIndicator.Show(OnLoggedIn, "There was a problem obtaining Roles, you have been logged in with the minimum security privelages", false, 10, true);
            }
        }

        /// <summary>
        /// Display technical error messages to admin, and a standard message to other users.
        /// </summary>
        /// <param name="errorMessage">The message to show admin.</param>
        void HandleError(string errorMessage)
        {
            if (Username.ToLower() != "admin")
                errorMessage = NonTechnicalErrorMessage;
            Cache.Start();
            Status = errorMessage;
            //"There was a technical Error" 
            BusyIndicator.Show(OnFocusUsername, errorMessage, false, 20, true);
        }

        void OnFocusUsername()
        {
            var handler = FocusUsername;
            if (handler != null)
                handler(this, EventArgs.Empty);
        }
        void OnLoggedIn()
        {
            var handler = LoggedIn;
            if (handler != null)
                handler(this, EventArgs.Empty);
        }


    }
}
